#pragma clang diagnostic push
#pragma ide diagnostic ignored "NullDereference"
#pragma ide diagnostic ignored "EndlessLoop"
#pragma ide diagnostic ignored "bugprone-branch-clone"
#include "main.h"
#pragma clang diagnostic ignored "-Wint-to-pointer-cast"
#pragma clang diagnostic ignored "-Wpointer-to-int-cast"
typedef struct stack stack;


int init_stack(Stack *s){
    int *a;
    a = (int *) malloc(STACK_MAX_SIZE * sizeof (int ));
    (*s) = malloc(sizeof  (struct stack));
    (*s)->base=a;
    (*s)->top=(*s)->base;
    (*s)->number_of_elements=STACK_MAX_SIZE;
    return 0;
}


int push(Stack s, char operator_or_operand){
    if (s->top - s->base == s->number_of_elements) {
        return 1;
    } else {
        *s->top = operator_or_operand;
    s->top+=1;
    }
    return 0;
}

int pop(Stack s, char * p_operator_or_operand){
    if (s->top - s->base == s->number_of_elements) {
        return 1;
    } else {
         char result=(char )*(s->top-1);
         s->top-=1;
         *p_operator_or_operand = result;

    }
    return 0;
}

int get_top(Stack s, char * symbol){
    char result;
    if (s->top - s->base == s->number_of_elements) {
        return 1;}
    else{
        result =  (char )*(s->top-1);
        *symbol = result;
    }
    return 0;
}


int is_operator(char symbol){
        switch (symbol) {
            case '#':
                return 1;
            case '(':
                return 1;
            case ')':
                return 1;
            case '+':
                return 1;
            case '-':
                return 1;
            case '*':
                return 1;
            case '/':
                return 1;
            default:
                return 0;
        }

}

int is_operand(char symbol){
    if(symbol>47&&symbol<58){
        return 1;
    } else if(symbol==0){
        return 1;
    } else{
        return 0;
    }

}
int is(char a){
    if(a=='#'||a=='+'||a=='-'||a=='*'||a=='/')
        return 1;//��
    else
        return 0;//����
}

int  Precede(char  symbol,char var){
    if(is_operator(symbol)&& is_operator(var)){
        char f = 0;
        if((char) symbol=='+'||(char) symbol=='-')
        {
            if(var=='+'||var=='-'||var==')'||var=='#')
                f='>';
            else if(var=='*'||var=='/'||var=='(')
                f='<';
        }
        else if((char) symbol=='*'||(char) symbol=='/')
        {
            if(var=='+'||var=='-'||var=='*'||var=='/'||var==')'||var=='#')
                f='>';
            else if(var=='(')
                f='<';
        }
        else if((char) symbol=='(')
        {
            if(var=='+'||var=='-'||var=='*'||var=='/'||var=='(')
                f='<';
            else if(var==')')
                f='=';
        }
        else if((char) symbol==')')
        {
            if(var=='+'||var=='-'||var=='*'||var=='/'||var==')'||var=='#')
                f='>';
        }
        else if((char) symbol=='#')
        {
            if(var=='+'||var=='-'||var=='*'||var=='/'||var=='(')
                f='<';
            else if(var=='#')
                f='=';
        }
        return f;
    } else{
        return 0;
    }

}
   int calculation(char * expression, int * result){
       switch (expression[0]) {
           case '+':
               *result =  (((int) expression[1]) + ((int)expression[2]));
               return 0;
           case '-':
               *result =  (((int) expression[1]) - ((int) expression[2]));
               return 0;
           case '*':
               *result =  (((int) expression[1]) * ((int) expression[2]));
               return 0;
           case '/':
               if(expression[1]==0||expression[2]==0){
                   printf("��ѧ�������Ϊ����0");
                   return 1;
               }
               *result =  (((int) expression[1]) / ((int) expression[2]));
               return 0;
}}


int evaluate(char * expression, int * result) {
    char var[STACK_MAX_SIZE] = {0};
    for (int o = 0; *expression != '\0'; ++o) {
        if(*expression=='#'&&o==0){
            expression += 1;
        }
        var[o] = *expression;
        expression += 1;
    }

    char varExpression[10];
    int result1 = 114514;
    char correct = '0';
    char res = 0;//��get����top��
    int i = 0;//����
    char p = 0;//pop�Ĳ�����
    char value1 = 0;//pop������
    char value2 = 0;//pop������
    char F;//������
    Stack OPND;
    Stack OPTR;
    init_stack((Stack *) &OPND);
    init_stack((Stack *) &OPTR);
    push(OPTR, '#');
    get_top(OPTR, &res);
    while (res != '#' || var[i-1] != '#') {
        if (is_operand(var[i]) == 1) {
            push(OPND, (char) ((int) var[i] - 48));
            if (is_operand(var[i + 1]) == 1) {
                printf(" ��ѧ���룺����Ϊ���ʽ����");
                return 1;
            } //�ж�������nd�󣬳˳��ź����Ŷ������ꡣ�ж����ڵ�tr���Ƿ�ֻʣ��һ�������ǵĻ�ֱ����ʾ�𰸣�����������������ֹһ��������������
        } else if (is_operator(var[i]) != 0) {
            get_top(OPTR, &res);
            switch (Precede(res, var[i])) {
                case '<':
                    push(OPTR, var[i]);
                    break;
                case '>':
                    if(OPND->top - OPND->base == 1){
                        printf(" ��ѧ���룺����Ϊ���ʽ����");
                        return 1;
                    }
                    pop(OPTR, &p);
                    pop(OPND, &value1);
                    pop(OPND, &value2);
                    varExpression[0] = p;
                    varExpression[1] = value2;
                    varExpression[2] = value1;
                    if (calculation(&varExpression[0], &result1) != 1) {
                        push(OPND, (char) result1);
                        get_top(OPTR, &res);
                        if (res == '(' && var[i] == ')') {//������
                            pop(OPTR, &F);
                            break;
                        } else if (var[i] == '#') {
                            break;
                        } else {
                            push(OPTR, var[i]);
                        }
                    } else {
                        printf(" ��ѧ���룺����Ϊ���ʽ����");
                        return 1;
                    }
                    break;
                case '=':
                    pop(OPTR, &F);
                    break;
                default:
                    printf(" ��ѧ���룺����Ϊ���ʽ����");
                    return 1;
            }

        }
        get_top(OPTR, &res);
        if (var[i] == '#' && is(res) && OPTR->top - OPTR->base != 1) {
            pop(OPTR, &correct);
            *result = correct;
        } else {
            i++;
        }
    }
    pop(OPND,&correct);
    *result = correct;
    return 0;
}

int main(void) {
    int F = 0;
    char *exp666 = "#(2*(3+5))+1#";
    evaluate(exp666, &F);
    printf("���Ϊ��");
    printf("%d", F);
}